package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.heart.domain.KingInvoicePayableDetailEntity;
import com.ly.heart.domain.KingInvoicePayableEntity;
import com.ly.heart.domain.KingInvoicePayableProcurePlanEntity;
import com.ly.heart.domain.KingOrgEntity;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.payable.*;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseError;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingInvoicePayableDetailService;
import com.ly.heart.service.IKingInvoicePayableProcurePlanService;
import com.ly.heart.service.IKingInvoicePayableService;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Wuzh
 * @Description:
 * @Date Created in 23:11 2024-07-15
 * @return
 */
@Component
@Slf4j
public class PayablePushService {

    @Resource
    private IKingInvoicePayableService iKingInvoicePayableService;
    @Resource
    private IKingInvoicePayableDetailService iKingInvoicePayableDetailService;
    @Resource
    private IKingInvoicePayableProcurePlanService iKingInvoicePayableProcurePlanService;
    @Resource
    private IKingOrgService iKingOrgService;

    public void push (KingInvoicePayableEntity payableEntity) {
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity> ().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity :: getIsDisabled, true ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        K3CloudApi client = new K3CloudApi ( identifyInfo );
        log.info ( "采购开票(应付单)调用金蝶下推 -> {}", payableEntity );
        KingInvoicePayableEntity kingInvoicePayableEntity = iKingInvoicePayableService.querySingleById ( payableEntity.getId () );
        if ( ObjectUtils.isEmpty ( payableEntity ) ) {
            throw new CustomException ( "采购开票(应付单)对象为空！" );
        }
        if ( kingInvoicePayableEntity.getIsSend () == KingConstUtil.KING_DATA_IS_SEND_YES ) {
            throw new CustomException ( "该单据已推送金蝶，无需重复推送！" );
        }
        PayableBo bo = assemblePayable ( kingInvoicePayableEntity );
        try {
            save ( bo, client );
            submit ( bo, client );
            audit ( bo, client );
            updateSendSuccess ( payableEntity.getId () );
        } catch ( Exception e ) {
            e.printStackTrace ();
            throw new CustomException ( "采购开票(应付单)保存失败" );
        }
    }

    /**
     * 下推采购开票(应付单)到金蝶
     * @param bo
     * @param client
     */
    private void save (PayableBo bo, K3CloudApi client) throws Exception {
        KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
        singleRequest.setModel ( bo );
        String s = JSONObject.toJSONString ( singleRequest );
        log.info ( "采购开票(应付单)转JSON->{}", s );
        String resultJson = client.save ( KingConstUtil.AP_Payable, s );
        //用于记录结果
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "采购开票(应付单)-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.info ( "{} 推送成功", sb );

        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "采购开票(应付单)-推送失败：【" + sb + "】" );
        }
    }


    /**
     * 提交采购开票(应付单)到金蝶
     * @param bo
     * @param client
     */
    private void submit (PayableBo bo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.submit ( KingConstUtil.AP_Payable, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "采购开票(应付单)-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 提交成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "采购开票(应付单)提交失败：【" + sb + "】" );
        }
    }

    /**
     * 审核应付单
     * @param bo
     * @param client
     */
    private void audit (PayableBo bo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.audit ( KingConstUtil.AP_Payable, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "采购开票(应付单)-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 审核成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "采购开票(应付单)审核失败：【" + sb + "】" );
        }
    }

    private void updateSendSuccess (String id) {
        KingInvoicePayableEntity payableEntity = new KingInvoicePayableEntity ();
        payableEntity.setId ( id );
        payableEntity.setIsSend ( KingConstUtil.KING_DATA_IS_SEND_YES );
        boolean b = iKingInvoicePayableService.updateById ( payableEntity );
        if ( ! b ) {
            throw new CustomException ( "修改推送金蝶状态失败！" );
        }
    }

    /**
     * 组装采购开票(应付单)下推金蝶的业务对象
     * @param kingInvoicePayableEntity
     * @return
     */
    private PayableBo assemblePayable (KingInvoicePayableEntity kingInvoicePayableEntity) {
        PayableBo bo = new PayableBo ();
        //1.基础信息
        //单据编码
        bo.setFBillNo ( kingInvoicePayableEntity.getDocNo () );
        //单据类型
        BaseChildBo billType = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getDocTypeCode () );
        bo.setFBillTypeID ( billType );
        //供应商
        BaseChildBo supplierBo = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getSupplierCode () );
        bo.setFSUPPLIERID ( supplierBo );
        //采购员，待处理

        //立账类型
        bo.setFSetAccountType ( kingInvoicePayableEntity.getAccountType () );
        //币别
        BaseChildBo currencyBo = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getCurrencyCode () );
        bo.setFCURRENCYID ( currencyBo );
        //业务日期
        bo.setFDate ( CommonUtil.getDateStrFormat ( kingInvoicePayableEntity.getBizTime (), "yyyy-MM-dd HH:mm:ss" ) );
        //到期日
        bo.setFENDDATE_H ( CommonUtil.getDateStrFormat ( kingInvoicePayableEntity.getDueTime (), "yyyy-MM-dd HH:mm:ss" ) );
        //付款条件
        BaseChildBo payConditionBo = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getCurrencyCode () );
        //bo.setFPayConditon ( payConditionBo );

        //采购部门
        BaseChildBo procureDept = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getProcureDeptCode () );
        bo.setFPURCHASEDEPTID ( procureDept );
        //按费用项目生成计划
        bo.setFIsGeneratePlanByCostItem ( "1".equals ( kingInvoicePayableEntity.getIsFee () ) ? true : false );
        //价外税
        bo.setFISPRICEEXCLUDETAX ( "1".equals ( kingInvoicePayableEntity.getIsExtraPriceTax () ) ? true : false );
        //按含税单价录入
        bo.setFISTAX ( "1".equals ( kingInvoicePayableEntity.getIsIncludeTaxPrice () ) ? true : false );
        //税额计入成本
        bo.setFISTAXINCOST ( "1".equals ( kingInvoicePayableEntity.getIsTaxCostAmount () ) ? true : false );
        //先到票后入库
        bo.setFISINVOICEARLIER ( "1".equals ( kingInvoicePayableEntity.getIsTicketsBefore () ) ? true : false );


        //2.供应商子对象
        FsubHeadSuppiler suppiler = new FsubHeadSuppiler ();
        //订货方
        BaseChildBo forder = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getForderCode () );
        suppiler.setFORDERID ( forder );
        //供货方
        BaseChildBo goods = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getGoodsCode () );
        suppiler.setFTRANSFERID ( goods );
        //收款方
        BaseChildBo receipt = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getReceiptCode () );
        suppiler.setFChargeId ( receipt );
        bo.setFsubHeadSuppiler ( suppiler );

        //3.财务子对象
        FsubHeadFinc fsubHeadFinc = new FsubHeadFinc ();
        //结算方式
        BaseChildBo settlementType = new BaseChildBo ().setFNumber ( kingInvoicePayableEntity.getSettlementCode () );
        fsubHeadFinc.setFSettleTypeID ( settlementType );
        //到期日计算日期
        fsubHeadFinc.setFACCNTTIMEJUDGETIME ( CommonUtil.getDateStrFormat ( kingInvoicePayableEntity.getDueCalculationTime (), "yyyy-MM-dd HH:mm:ss" ) );
        bo.setFsubHeadFinc ( fsubHeadFinc );

        //4.明细列表
        List<FEntityDetail> fEntityDetails = assembleFEntityDetail ( kingInvoicePayableEntity.getId () );
        bo.setFEntityDetail ( fEntityDetails );

        //5.付款计划列表
        List<FEntityPlan> fEntityPlans = assembleFEntityPlan ( kingInvoicePayableEntity.getId () );
        bo.setFEntityPlan ( fEntityPlans );
        return bo;
    }

    /**
     * 根据应付单Id处理物料明细列表
     * @param payableId
     * @return
     */
    private List<FEntityDetail> assembleFEntityDetail (String payableId) {
        List<KingInvoicePayableDetailEntity> invoicePayableDetailEntities = iKingInvoicePayableDetailService.list ( new QueryWrapper<KingInvoicePayableDetailEntity> ().
                eq ( "invoice_payable_id", payableId ) );
        List<FEntityDetail> fEntityDetails = new ArrayList<> ();
        for ( int i = 0; i < invoicePayableDetailEntities.size (); i++ ) {
            KingInvoicePayableDetailEntity detailEntity = invoicePayableDetailEntities.get ( i );
            FEntityDetail fEntityDetail = new FEntityDetail ();
            //物料编码
            BaseChildBo materialCode = new BaseChildBo ().setFNumber ( detailEntity.getMaterialCode () );
            fEntityDetail.setFMATERIALID ( materialCode );
            //费用项目编码
            BaseChildBo feeCode = new BaseChildBo ().setFNumber ( detailEntity.getFeeCode () );
            fEntityDetail.setFCOSTID ( feeCode );
            //计价单位
            BaseChildBo unit = new BaseChildBo ().setFNumber ( detailEntity.getUnit () );
            fEntityDetail.setFPRICEUNITID ( unit );
            //单价
            fEntityDetail.setFPrice ( detailEntity.getTaxPrice () );
            //计价数量
            fEntityDetail.setFPriceQty ( detailEntity.getNum () ).
                    setFStockQty ( detailEntity.getNum () ).
                    setFStockBaseQty ( detailEntity.getNum () );
            //含税单价
            fEntityDetail.setFTaxPrice ( detailEntity.getTaxPrice () );
            //税率
            fEntityDetail.setFEntryTaxRate ( detailEntity.getRate () );
            //折扣率
            fEntityDetail.setFEntryDiscountRate ( detailEntity.getDiscountRate () );
            //折扣额
            fEntityDetail.setFDISCOUNTAMOUNTFOR ( detailEntity.getDiscountAmount () );
            //不含税金额
            fEntityDetail.setFNoTaxAmountFor_D ( detailEntity.getNotTaxAmount () );
            //税额
            fEntityDetail.setFTAXAMOUNTFOR_D ( detailEntity.getRateAmount () );
            //价税合计
            fEntityDetail.setFALLAMOUNTFOR_D ( detailEntity.getTotalTaxPrice () );
            //是否赠品
            fEntityDetail.setFIsFree ( detailEntity.getIsGift () );
            //库存单位
            BaseChildBo stockUnit = new BaseChildBo ().setFNumber ( detailEntity.getUnit () );
            fEntityDetail.setFStockUnitId ( stockUnit );
            //是否计入采购成本
            fEntityDetail.setFINCLUDECOST ( detailEntity.getIsIncludeProcureCost () );
            //是否计入合同履约成本
            fEntityDetail.setFINCLUDECONTRACTCOMPCOST ( detailEntity.getIsIncludeContractCost () );
            //费用承担部门
            BaseChildBo dept = new BaseChildBo ().setFNumber ( detailEntity.getBearDeptCode () );
            fEntityDetail.setFCOSTDEPARTMENTID ( dept );

            fEntityDetails.add ( fEntityDetail );
        }
        return fEntityDetails;
    }


    /**
     * 通过应付单Id组装付款计划列表
     * @param payableId
     * @return
     */
    private List<FEntityPlan> assembleFEntityPlan (String payableId) {
        List<FEntityPlan> fEntityPlanList = new ArrayList<> ();
        List<KingInvoicePayableProcurePlanEntity> payableProcurePlanEntities = iKingInvoicePayableProcurePlanService.list ( new QueryWrapper<KingInvoicePayableProcurePlanEntity> ().
                eq ( "invoice_payable_id", payableId ) );
        payableProcurePlanEntities.forEach ( planEntity -> {
            FEntityPlan fEntityPlan = new FEntityPlan ();
            //到期日
            fEntityPlan.setFENDDATE ( CommonUtil.getDateStrFormat ( planEntity.getDueTime (), "yyyy-MM-dd HH:mm:ss" ) );
            //应付金额
            fEntityPlan.setFPAYAMOUNTFOR ( planEntity.getPayAmount () );
            //应付比例
            fEntityPlan.setFPAYRATE ( planEntity.getPayRatio () );
            fEntityPlanList.add ( fEntityPlan );
        } );
        return fEntityPlanList;
    }

}
